package com.macrounion.atv.processor;

import com.macrounion.atv.service.dto.resp.SmartInsertRespDto;
import com.macrounion.atv.service.entity.Channel;
import com.macrounion.atv.service.entity.CurrentData;
import com.macrounion.atv.service.entity.ext.ProtocolCExt;
import com.macrounion.atv.service.service.CurrentDataService;
import com.macrounion.base.service.dto.BaseRespDto;
import com.macrounion.base.service.dto.PageRespDto;
import com.macrounion.base.service.dto.StringRespDto;
import io.swagger.models.auth.In;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Component;

import com.macrounion.atv.service.entity.ProtocolC;
import com.macrounion.atv.service.service.ProtocolCService;
import com.macrounion.base.processor.BaseProcessor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

@Component
public class ProtocolCProcessor extends BaseProcessor<ProtocolC, ProtocolC, ProtocolCService, ProtocolC> {
    @Autowired
    CurrentDataService currentDataService;

    @Autowired
    ChannelProcessor channelProcessor;

    @CacheEvict(value = "protocolc", key = "#protocolId")
    public int deleteRows(String protocolId, List<String> ids) {
        return service.deleteRows(ids);
    }

    public String getMaxChannelCodeByProtocolId(String protocolId, Integer trap) {
        return this.service.getMaxChannelCodeByProtocolId(protocolId, trap);
    }

    public int getCountByMid(String mid, String protocolId) {
        return this.service.getCountByMid(mid, protocolId);
    }

    public int getCountByChannelCode(String channelCode, String protocolId) {
        return this.service.getCountByChannelCode(channelCode, protocolId);
    }

    @CacheEvict(value = "protocolc", key = "#protocolId")
    public int deleteByProtocolId(String protocolId) {
        return this.service.deleteByProtocolId(protocolId);
    }

    @Transactional
    @CacheEvict(value = "protocolc", key = "#protocolId")
    public int saveProtocols(String protocolId, List<ProtocolC> protocolCS) {
        int channelCodeInt = 0;
        List<ProtocolC> protocolCList = new ArrayList<>();
        List<Integer> existCommonChannelCode = getExistedCommonChannelCode(protocolCS);
        List<Integer> existTrapChannelCode = getExistedTrapChannelCode(protocolCS);
        //对通道号进行处理，剔除特殊通道号，并格式化通道号
        for (ProtocolC protocolC : protocolCS) {
            switch (protocolC.getTrap()) {
                case 0:
                    if (!protocolC.getChannelCode().isEmpty()) {
                        channelCodeInt = Integer.parseInt(protocolC.getChannelCode());
                    } else {
                        channelCodeInt = getChannelCodeIntNoRepeats(channelCodeInt + 1, existCommonChannelCode);
                    }
                    if (channelCodeInt == 0 || channelCodeInt == 999) {
                        continue;
                    }
                    String channelCode = generateCommonChannelCode(channelCodeInt, protocolId);
                    protocolC.setChannelCode(channelCode);
                    break;
                case 1:
                    if (!protocolC.getChannelCode().isEmpty()) {
                        if (protocolC.getChannelCode().startsWith("t")) {
                            channelCodeInt = Integer.parseInt(protocolC.getChannelCode().substring(1));
                        } else {
                            channelCodeInt = Integer.parseInt(protocolC.getChannelCode());
                        }
                    } else {
                        channelCodeInt = getChannelCodeIntNoRepeats(channelCodeInt + 1, existTrapChannelCode);
                    }
                    if (channelCodeInt == 0 || channelCodeInt == 999) {
                        continue;
                    }
                    String trapChannelCode = generateTrapChannelCode(channelCodeInt, protocolId);
                    protocolC.setChannelCode(trapChannelCode);
                    break;
                default:
            }
            protocolCList.add(protocolC);
        }
        return this.service.saveProtocols(protocolCList);
    }

    /**
     * 获取常规通道号已有表
     *
     * @param protocolCS
     * @return
     */
    private List<Integer> getExistedCommonChannelCode(List<ProtocolC> protocolCS) {
        List<Integer> exitedChannelCode = new ArrayList<>();
        for (ProtocolC protocolC : protocolCS) {
            if (protocolC.getTrap() == 0) {
                if (null != protocolC.getChannelCode() && !"".equals(protocolC.getChannelCode())) {
                    exitedChannelCode.add(Integer.parseInt(protocolC.getChannelCode()));
                }
            }
        }
        return exitedChannelCode;
    }

    /**
     * 获取trap通道号已有表
     *
     * @param protocolCS
     * @return
     */
    private List<Integer> getExistedTrapChannelCode(List<ProtocolC> protocolCS) {
        List<Integer> exitedChannelCode = new ArrayList<>();
        for (ProtocolC protocolC : protocolCS) {
            if (protocolC.getTrap() == 1) {
                if (null != protocolC.getChannelCode() && !"".equals(protocolC.getChannelCode())) {
                    exitedChannelCode.add(Integer.parseInt(protocolC.getChannelCode().substring(1)));
                }
            }
        }
        return exitedChannelCode;
    }

    private int getChannelCodeIntNoRepeats(int channelCodeInt, List<Integer> existChannelCode) {
        if (existChannelCode.contains(channelCodeInt)) {
            return getChannelCodeIntNoRepeats(channelCodeInt + 1, existChannelCode);
        } else {
            existChannelCode.add(channelCodeInt);
            return channelCodeInt;
        }
    }

    private String generateCommonChannelCode(int channelCodeInt, String protocolId) {
        if (channelCodeInt < 10) {
            if (service.getCountByChannelCode("00" + channelCodeInt, protocolId) > 0) {
                generateCommonChannelCode(channelCodeInt + 1, protocolId);
            }
            return "00" + channelCodeInt;
        } else if (channelCodeInt < 100) {
            if (service.getCountByChannelCode("0" + channelCodeInt, protocolId) > 0) {
                generateCommonChannelCode(channelCodeInt + 1, protocolId);
            }
            return "0" + channelCodeInt;
        } else {
            if (service.getCountByChannelCode("" + channelCodeInt, protocolId) > 0) {
                generateCommonChannelCode(channelCodeInt + 1, protocolId);
            }
            return "" + channelCodeInt;
        }
    }

    private String generateTrapChannelCode(int channelCodeInt, String protocolId) {
        if (channelCodeInt < 10) {
            if (service.getCountByChannelCode("t00" + channelCodeInt, protocolId) > 0) {
                generateTrapChannelCode(channelCodeInt + 1, protocolId);
            }
            return "t00" + channelCodeInt;
        } else if (channelCodeInt < 100) {
            if (service.getCountByChannelCode("t0" + channelCodeInt, protocolId) > 0) {
                generateTrapChannelCode(channelCodeInt + 1, protocolId);
            }
            return "t0" + channelCodeInt;
        } else {
            if (service.getCountByChannelCode("t" + channelCodeInt, protocolId) > 0) {
                generateTrapChannelCode(channelCodeInt + 1, protocolId);
            }
            return "t" + channelCodeInt;
        }
    }

    /**
     * 对traplist的通道号进行处理
     *
     * @param protocolId
     * @param protocolC
     */
    private void handelTrapChannelCode(String protocolId, ProtocolC protocolC) {
        String maxChannelCode = getMaxChannelCodeByProtocolId(protocolId, 1);
        String substring = maxChannelCode.substring(1);
        int maxChannelCodeInt = Integer.parseInt(substring) + 1;
        if (maxChannelCodeInt < 10) {
            protocolC.setChannelCode("t00" + maxChannelCodeInt);
        } else if (maxChannelCodeInt < 100) {
            protocolC.setChannelCode("t0" + maxChannelCodeInt);
        } else {
            protocolC.setChannelCode("t" + maxChannelCodeInt);
        }
    }

    @Transactional
    @CacheEvict(value = "protocolc", key = "#protocolId")
    public StringRespDto saveAProtocolc(String protocolId, ProtocolC req) {
        //mid验证
        if (null == req.getMid() || req.getMid().isEmpty()) {
            return new StringRespDto("请输入id!");
        } else if (null == req.getId() || req.getId().isEmpty()) {
            int count = getCountByMid(req.getMid(), protocolId);
            if (count > 0) {
                return new StringRespDto("id已存在！");
            }
        } else {
            ProtocolC byId = findById(req.getId());
            if (!req.getMid().equals(byId.getMid())) {
                int count = getCountByMid(req.getMid(), protocolId);
                if (count > 0) {
                    return new StringRespDto("id已存在！");
                }
            }
        }
        //通道号验证
        if (null == req.getChannelCode() || req.getChannelCode().isEmpty()) {
            return new StringRespDto("请输入通道号！");
        } else if (null == req.getId() || req.getId().isEmpty()) {
            int count = getCountByChannelCode(req.getChannelCode(), protocolId);
            if (count > 0) {
                return new StringRespDto("通道号已存在！");
            }
        } else {
            ProtocolC byId = findById(req.getId());
            if (!req.getChannelCode().equals(byId.getChannelCode())) {
                int count = getCountByChannelCode(req.getChannelCode(), protocolId);
                if (count > 0) {
                    return new StringRespDto("通道号已存在！");
                }
            }
        }
        if (req.getTrap() == 0) {
            if (req.getChannelCode().equals("000") || req.getChannelCode().equals("999")) {
                return new StringRespDto("通道号不能为000或999");
            }
            if (Integer.parseInt(req.getChannelCode()) > 999) {
                return new StringRespDto("超出最大通道号限制！");
            }
        }
        //监控名称验证
        if (null == req.getName() || req.getName().isEmpty()) {
            return new StringRespDto("请输入监控名称或描述！");
        }
        //类型验证
        if (req.getTrap() == 0) {
            if (req.getDataType() == null) {
                return new StringRespDto("请选择类型！");
            }
        }
        //格式化通道号
        if (req.getTrap() == 0) {
            int intChannelCode = Integer.parseInt(req.getChannelCode());
            if (intChannelCode < 10) {
                req.setChannelCode("00" + intChannelCode);
            } else if (intChannelCode < 100) {
                req.setChannelCode("0" + intChannelCode);
            }
        }
        save(req);
        return new StringRespDto("保存成功！");
    }


    public String getNameByChannelCodeNPid(String channelCode, String protocolId) {
        return this.service.getNameByChannelCodeNPid(channelCode, protocolId);
    }

    @Transactional
    public SmartInsertRespDto smartImport(String deviceCode, String protocolId, String protocolName, List<String> protocolCIds) {
        int result = 0;
        List<CurrentData> currentDataList = currentDataService.getCurrentDataByDeviceCode(deviceCode);
        if (currentDataList.size() == 0) {
            return SmartInsertRespDto.fail("errorDeviceCode");
        }
        if (protocolCIds.size() > 0) {
            result = deleteRows(protocolId, protocolCIds);
            if (result <= 0) {
                return SmartInsertRespDto.fail("获取失败，请稍后再试");
            }
        }
        List<ProtocolC> protocolCList = new ArrayList<>();
        if (currentDataList.size() > 0) {
            //对000和998及以上的协议号进行剔除
            for (CurrentData currentData : currentDataList) {
                if (Integer.parseInt(currentData.getChannelCode()) > 998
                        || Integer.parseInt(currentData.getChannelCode()) == 0) {
                    continue;
                }
                Channel channel = channelProcessor.findById(currentData.getChannelId() == null ? "" : currentData.getChannelId());
                ProtocolC protocolC = new ProtocolC();
                protocolC.setDataType(channel == null ? null : channel.getDataType());
                protocolC.setName(currentData.getChannelId() != null ?
                        (currentData.getChannelId().length() > 20 ?
                                currentData.getChannelId().substring(20) : currentData.getChannelId()) : null);
                protocolC.setChannelCode(currentData.getChannelCode());
                protocolC.setMid(currentData.getId());
                protocolC.setUnit(currentData.getUnit());
                protocolC.setTrap(0);
                protocolC.setId(UUID.randomUUID().toString());
                protocolC.setProtocolName(protocolName);
                protocolC.setProtocolId(protocolId);
                protocolC.setCreatedTime(new Date());
                protocolCList.add(protocolC);
            }
            //保存协议详情
            int i = saveProtocols(protocolId, protocolCList);
            if (i > 0) {
                return SmartInsertRespDto.success(requestPage(new ProtocolC()));
            } else {
                return SmartInsertRespDto.fail("获取失败，请稍后再试");
            }
        } else {
            return SmartInsertRespDto.fail("获取失败，请稍后再试");
        }
    }

    public PageRespDto<ProtocolCExt> requestPageExt(ProtocolC req) {
        PageRespDto<ProtocolC> pageRespDto = super.requestPage(req);
        PageRespDto<ProtocolCExt> respDto = new PageRespDto<>();
        List<ProtocolC> dataList = pageRespDto.getDataList();
        List<ProtocolCExt> resultList = new ArrayList<>();
        if (null != dataList && !dataList.isEmpty()) {
            for (ProtocolC protocolC : dataList) {
                ProtocolCExt protocolCExt = new ProtocolCExt();
                BeanUtils.copyProperties(protocolC, protocolCExt);
                resultList.add(protocolCExt);
            }
            resultList.sort(Comparator.reverseOrder());
        }
        respDto.setDataList(resultList);
        respDto.setPageNum(pageRespDto.getPageNum());
        respDto.setPageSize(pageRespDto.getPageSize());
        respDto.setTotal(pageRespDto.getTotal());
        respDto.setPages(pageRespDto.getPages());
        return respDto;
    }

    @Transactional
    @CacheEvict(value = "protocolc", key = "#protocolId")
    public BaseRespDto<String> updateTranslate(String protocolId, ProtocolC protocolC) {
        if (!StringUtils.isEmpty(protocolC.getTranslate()) && protocolC.getTranslate().length() > 200) {
            return new BaseRespDto<>(202, "转译表达式不能超过200个字符");
        }
        int i = service.updateTranslate(protocolC);
        if (i < 1) {
            return new BaseRespDto<>(201, "保存失败！");
        }
        return new BaseRespDto<>(200, "保存成功！");
    }
}